package org.spidermesh.meshlog.core.log;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spidermesh.meshlog.annotation.MeshLog;
import org.spidermesh.meshlog.config.MeshDict;
import org.spidermesh.meshlog.core.log.interfaces.LogManager;
import org.spidermesh.meshlog.model.LogInfo;
import org.spidermesh.meshlog.properties.MeshLogProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @PackageName:com.wms.config
 * @ClassName:MeshLog
 * @Description:
 * @Author:hw
 * @Date:2020-11-23 17:23
 */
@Aspect
@Component
@ConditionalOnBean(value = MeshLogProperties.class)
public class MeshLogAop {

    private static final Logger logger= LoggerFactory.getLogger(MeshLog.class);
    private static final DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static LocalDateTime dateTime;
    @Autowired
    MeshLogProperties properties;
    @Autowired
    LogManager logManager;

//    @Pointcut("execution(* com.wms.controller..*.*(..)) || @annotation(com.wms.config.MeshLog)")
    @Pointcut("@annotation(org.spidermesh.meshlog.annotation.MeshLog)")
    public void MeshPoint(){}

    @Async
    @Before(value = "MeshPoint()")
    public void logBefore(JoinPoint joinPoint){
        MethodSignature methodSignature=(MethodSignature)joinPoint.getSignature();

        Method method=methodSignature.getMethod();
        MeshLog meshLog=method.getAnnotation(MeshLog.class);
        String tag=joinPoint.getTarget().getClass().getSimpleName()+">"+method.getName();
        MeshDict type=MeshDict.LOG_TYPE_MESH;
        if (null!=meshLog){
            if (!"".equals(meshLog.tag())){
                tag=meshLog.tag();
            }
            if (MeshDict.LOG_TYPE_MESH!=meshLog.type()){
                type=meshLog.type();
            }
        }

        Object[] args=joinPoint.getArgs();
        String infostr= JSON.toJSONString(args);

        LogInfo logInfo=new LogInfo();
        logInfo.setPrefix(properties.getPrefix());
        logInfo.setTag(tag);
        logInfo.setLacation(MeshDict.LOG_LOCATION_INPUT.getName());
        logInfo.setInfo(infostr);

        logManager.doLog(logInfo,properties);
    }

    @Async
    @AfterReturning(returning = "result",pointcut = "MeshPoint()")
    public void logAfter(JoinPoint joinPoint,Object result){
        MethodSignature methodSignature=(MethodSignature)joinPoint.getSignature();
        Method method=methodSignature.getMethod();
        MeshLog meshLog=method.getAnnotation(MeshLog.class);
        String tag=joinPoint.getTarget().getClass().getSimpleName()+">"+method.getName();
        MeshDict type=MeshDict.LOG_TYPE_MESH;
        if (null!=meshLog){
            if (!"".equals(meshLog.tag())){
                tag=meshLog.tag();
            }
            if (MeshDict.LOG_TYPE_MESH!=meshLog.type()){
                type=meshLog.type();
            }
        }

        String infostr= JSON.toJSONString(result);
        LogInfo logInfo=new LogInfo();
        logInfo.setPrefix(properties.getPrefix());
        logInfo.setTag(tag);
        logInfo.setLacation(MeshDict.LOG_LOCATION_INPUT.getName());
        logInfo.setInfo(infostr);

        logManager.doLog(logInfo,properties);

    }

}
